package com.zhy.deploy.executor.defaultImpl;

import cn.hutool.core.util.StrUtil;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
import com.zhy.deploy.config.BuildMetadata;
import com.zhy.deploy.config.GitConfig;
import com.zhy.deploy.executor.AbstractExecutor;
import com.zhy.deploy.websocket.SocketMessage;
import hudson.model.TaskListener;
import hudson.plugins.git.GitException;
import hudson.util.StreamTaskListener;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.URIish;
import org.jenkinsci.plugins.gitclient.FetchCommand;
import org.jenkinsci.plugins.gitclient.Git;
import org.jenkinsci.plugins.gitclient.GitClient;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;

public class DefaultGitExecutor extends AbstractExecutor {

    public DefaultGitExecutor(BuildMetadata metadata) {
        super(metadata);
    }

    @Override
    public void execute() throws Exception {

        GitConfig gitConfig = metadata.getGitConfig();
        SocketMessage socketMessage = metadata.getMessage();

        String gitRepoURL = gitConfig.getGitRepoURL();
        if(StrUtil.isEmpty(gitRepoURL)){
            socketMessage.error("请设置正确的远程仓库地址");
            throw new GitException("请设置正确的远程仓库地址");
        }

        String localRepo = gitConfig.getLocalRepo();

        if(StrUtil.isEmpty(localRepo)){
            String projectName = metadata.getProjectName();
            String workspace = metadata.getWorkspace();
            localRepo = new StringBuffer().append(workspace).append(File.separator).append(projectName).toString();
        }

        File repo = new File(localRepo);

        TaskListener listener = Objects.nonNull(socketMessage) ? new StreamTaskListener(socketMessage) : StreamTaskListener.fromStderr();

        GitClient git = Git.with(listener, new hudson.EnvVars()).in(repo).using("git").getClient();

        if(!git.hasGitRepo()){
            git.init_().workspace(repo.getAbsolutePath()).execute();
        }

        String username = gitConfig.getUsername();
        String password = gitConfig.getPassword();
        if(StrUtil.isNotEmpty(username) && StrUtil.isNotEmpty(password)){
            addCredential(git, username, password);
        }

        doFetch(git, gitRepoURL,gitConfig.getBranch(),true);

        ObjectId master = git.getHeadRev(gitRepoURL, "master");

        git.checkout().branch("master").ref(master.getName()).deleteBranchIfExist(true).execute();
    }

    private static void addCredential(GitClient git,String username,String password) throws IOException {
        CredentialsScope scope = CredentialsScope.GLOBAL;
        String id = "username-" + username + "-password-" + password + new Random().nextInt();
        UsernamePasswordCredentialsImpl credentials = new UsernamePasswordCredentialsImpl(scope, id, "desc: " + id, username, password);
        git.addDefaultCredentials(credentials);
    }

    private static void doFetch(GitClient git,String source, String branch, Boolean allowShallowClone) throws Exception {
        /* Save some bandwidth with shallow clone for CliGit, not yet available for JGit */
        URIish sourceURI = new URIish(source);
        List<RefSpec> refSpecs = new ArrayList<>();
        refSpecs.add(new RefSpec("+refs/heads/"+branch+":refs/remotes/origin/"+branch+""));
        FetchCommand cmd = git.fetch_().from(sourceURI, refSpecs).tags(false);
        cmd.execute();
    }

}
